Surveiller les créations,modifications et suppression de fichier dans un répertoire
Table des matières
Surveiller une arborescence de répertoires pour les modifications
4. Comprendre les événements inotify
6. Integrating the inotifywait Output With Another Script
Dans ce didacticiel, nous apprendrons à utiliser inotifywait pour surveiller les modifications d'une arborescence de répertoires. Par exemple, nous verrons comment détecter la création d'un nouveau fichier.
Nous allons commencer par une introduction au problème. Ensuite, nous en apprendrons davantage sur les événements inotify . Enfin, nous parlerons de la commande inotifywait et de la façon de l'utiliser pour résoudre le problème.
Puisque nos exemples utiliseront la commande inotifywait , nous voudrons nous assurer qu'elle est installée. S'il n'est pas installé, nous pouvons l'ajouter en installant le package inotify-tools . Si nous avons une distribution Debian ou similaire, nous pouvons exécuter la commande apt-get en tant que root pour installer le paquet :
$ apt-get install inotify-tools
D'un autre côté, si nous avons une distribution Red Hat ou similaire, nous pouvons utiliser la commande yum , mais nous devons d'abord installer le référentiel epel-release :
$ yum install epel-release
$ yum install inotify-tools
Commençons par un répertoire appelé main , qui contient plusieurs sous-répertoires. Avec la commande tree , nous pouvons voir l'arborescence de notre répertoire principal :
$ tree main/
main/
├── 1
│ ├── 1
│ └── 2
│ └── 1
├── 2
└── 3
├── 1
└── 2
└── 1
└── 1
10 directories, 0 files
Tout d'abord, nous allons surveiller cette arborescence de répertoires. Par exemple, nous pouvons savoir quand un fichier est créé ou supprimé, ouvert, écrit, lu ou fermé. Ensuite, nous utiliserons ces informations pour exécuter d'autres programmes lorsque nous détecterons un événement sur cette arborescence de répertoires. Par exemple, nous pouvons alerter l'utilisateur lorsqu'un processus supprime un fichier dans cette arborescence de répertoires.
Sous Linux, nous pouvons utiliser l' interface inotify pour surveiller un répertoire ou un fichier. Nous faisons cela en ajoutant une montre au répertoire ou au fichier. Lorsque nous ajoutons une montre à un fichier, nous pouvons le surveiller . Par exemple, nous saurons quand un processus ouvre, modifie, lit, ferme, déplace ou supprime le fichier. Lorsque nous ajoutons une surveillance à un répertoire, nous surveillons également les événements dans n'importe quel fichier de ce répertoire . De plus, nous pouvons savoir si un autre processus crée, supprime ou déplace un fichier dans ce répertoire. Nous pouvons choisir de surveiller tous les événements ou de ne surveiller que certains d'entre eux. Le système nous avertira lorsque l'un de ces événements se produira.
Nous pouvons utiliser la commande inotifywait pour surveiller une arborescence de répertoires. Pour surveiller une arborescence de répertoires, y compris ses sous-répertoires, nous utiliserons le paramètre -r . De plus, nous devons utiliser le paramètre -m . Cela configure inotifywait pour continuer à surveiller le répertoire pour toujours. Sinon, inotifywait se termine après le premier événement. Voyons comment surveiller n'importe quel événement dans notre répertoire principal :
$ inotifywait -m -r main
Setting up watches. Beware: since -r was given, this may take a while!
Watches established.
Avec cela, la commande inotifywait continuera à s'exécuter au premier plan, en attendant les événements. Maintenant, pendant que inotifywait est toujours en cours d'exécution, ouvrons un nouveau shell et exécutons echo example > main/1/2/file1 . Cette commande crée un nouveau fichier dans le dossier main/1/2 . Revenons au shell où nous exécutons inotifywait pour voir sa sortie :
main/1/2/ CREATE file1
main/1/2/ OPEN file1
main/1/2/ MODIFY file1
main/1/2/ CLOSE_WRITE,CLOSE file1
Nous pouvons voir que la sortie inotifywait a trois colonnes. Tout d'abord, le répertoire de base, puis l'événement et enfin le fichier qui a déclenché cet événement. Maintenant, créons un nouveau dossier appelé 1 dans le répertoire main/2 . Ensuite, nous allons créer un nouveau fichier appelé file1 dans le nouveau répertoire :
$ mkdir main/2/1
$ echo example > main/2/1/file1
Voyons la sortie inotifywait :
main/2/ CREATE,ISDIR 1
main/2/ OPEN,ISDIR 1
main/2/ ACCESS,ISDIR 1
main/2/ CLOSE_NOWRITE,CLOSE,ISDIR 1
main/2/1/ CREATE file1
main/2/1/ OPEN file1
main/2/1/ MODIFY file1
main/2/1/ CLOSE_WRITE,CLOSE file1
We can notice that inotifywait automatically watches for events in the new directory. Finally, let’s see how we can specify the exact events we want to monitor. To do this, we’ll use the -e parameter and add the desired events separated by commas. First, let’s finish the previous inotifywait command with Control+C. Then, let’s monitor only for create and modify events:
$ inotifywait -m -r -e create,modify main
Now, let’s write to the main/1/2/file1 file and then create a new empty file called file2 inside the main/1/2 directory:
$ echo example2 >> main/1/2/file1
$ touch main/1/2/file2
Let’s see the new output:
main/1/2/ MODIFY file1
main/1/2/ CREATE file2
So far, we have learned how to use inotifywait. So now, let’s create a script to run another program depending on the events inotifywait reports. First, let’s write a function that runs xmessage to inform the user that a file was removed:
$ file_removed() {
xmessage "$2 was removed from $1" &
}
This function receives two parameters. The first one is the directory, and the other is the file that was removed. Also, we’ll run xmessage in the background, so the function doesn’t block. Then, let’s write two functions to write to a log file when a file is modified and created:
$ file_modified() {
TIMESTAMP=`date`
echo "[$TIMESTAMP]: The file $1$2 was modified" >> monitor_log
}
$ file_created() {
TIMESTAMP=`date`
echo "[$TIMESTAMP]: The file $1$2 was created" >> monitor_log
}
Now, we can parse the inotifywait output feeding it to a while loop. We’ll split the directory, event, and file field from the output using the read command. Next, we can use the case command to decide which function to call depending on the event. Additionally, we’ll add the -q parameter to the inotifywait command so that inotifywait only prints the events without printing the initial message. Let’s put all of this together in a script called monitor_directory_tree.sh. This script receives the directory to monitor as the first parameter. Then, it calls the corresponding function when inotifywait reports an event:
#!/bin/bash
file_removed() {
xmessage "$2 was removed from $1" &
}
file_modified() {
TIMESTAMP=`date`
echo "[$TIMESTAMP]: The file $1$2 was modified" >> monitor_log
}
file_created() {
TIMESTAMP=`date`
echo "[$TIMESTAMP]: The file $1$2 was created" >> monitor_log
}
inotifywait -q -m -r -e modify,delete,create $1 | while read DIRECTORY EVENT FILE; do
case $EVENT in
MODIFY*)
file_modified "$DIRECTORY" "$FILE"
;;
CREATE*)
file_created "$DIRECTORY" "$FILE"
;;
DELETE*)
file_removed "$DIRECTORY" "$FILE"
;;
esac
done
Let’s test this script by first running monitor_directory_tree.sh in the background. Then we’ll remove the main/3/2/1 directory. Next, we’ll write some text to the main/1/2/file1 file. Finally, we’ll create and write to the main/file1 file:
$ ./monitor_directory_tree.sh main &
[1] 4800
$ rm -r main/3/2/1
$ echo example >> main/1/2/file1
$ echo example >> main/file1
With this, we can notice that two xmessage alerts appeared. One alert says “1 was removed from main/3/2/1” and the other alert says “1 was removed from main/3/2”. This is because when we run rm -r main/3/2/1, it also removed the main/3/2/1/1 subdirectory. Now, let’s look at the monitor_log file:
$ cat monitor_log
[Tue Sep 21 21:49:31 -03 2021]: The file main/1/2/file1 was modified
[Wed Sep 21 21:49:34 -03 2021]: The file main/file1 was created
[Wed Sep 21 21:49:34 -03 2021]: The file main/file1 was modified
We can see, the log shows that we modified main/1/2/file1. Then it shows that the file main/file1 was created and modified, just as we did.